package com.elitesland.core.base;

import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.val;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * REST API 返回结果
 * </p>
 *
 * @author Mir
 * @date 2018-11-08
 */
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
public class ApiResult<T> implements Serializable {

    private static final long serialVersionUID = 7722914707623525357L;

    /**
     * 响应码
     */
    private int code;

    /**
     * 响应消息
     */
    private String msg;

    /**
     * 是否成功
     */
    private boolean success;

    /**
     * 响应数据
     */
    private T data;

    /**
     * 响应时间
     */
//    @JSONField(format = "yyyy-MM-ddTHH:mm:ss")
//    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime time = LocalDateTime.now();

    public ApiResult() {

    }

    public static <T> ApiResult<T> result(boolean flag) {
        if (flag) {
            return ok();
        }
        return fail();
    }

    public static <T> ApiResult<T> result(ApiCode apiCode) {
        return result(apiCode, null);
    }

    public static <T> ApiResult<T> result(ApiCode apiCode, T data) {
        return result(apiCode, null, data);
    }

    public static <T> ApiResult<T> result(ApiCode apiCode, String msg, T data) {
        boolean success = false;
        if (apiCode.getCode() == ApiCode.SUCCESS.getCode()) {
            success = true;
        }
        String message = apiCode.getMsg();
        if (StrUtil.isNotBlank(msg)) {
            message = msg;
        }
        return ApiResult.<T>builder()
                .code(apiCode.getCode())
                .msg(message)
                .data(data)
                .success(success)
                .time(LocalDateTime.now())
                .build();
    }

    public static <T> ApiResult<T> ok() {
        return ok(null);
    }

    public static <T> ApiResult<T> ok(T data) {
        return result(ApiCode.SUCCESS, data);
    }

    public static <T> ApiResult<T> ok(T data, String msg) {
        return result(ApiCode.SUCCESS, msg, data);
    }

    public static <T> ApiResult<Map<String, T>> okMap(String key, T value) {
        Map<String, T> map = new HashMap<>(1);
        map.put(key, value);
        return ok(map);
    }

    public static Map<String, Object> toMap(ApiResult<?> result) {
        val map = new HashMap<String, Object>();
        map.put("code", result.code);
        map.put("msg", result.msg);
        map.put("data", result.data);
        map.put("success", result.success);
        map.put("time", result.time);

        return map;
    }

    public static <T> ApiResult<T> fail(ApiCode apiCode) {
        return result(apiCode, null);
    }

    public static <T> ApiResult<T> fail(String msg) {
        return result(ApiCode.FAIL, msg, null);

    }

    public static ApiResult<Object> fail(ApiCode apiCode, String msg){
        if(ApiCode.SUCCESS == apiCode){
            throw new RuntimeException("失败结果状态吗不能为" + ApiCode.SUCCESS.getCode());
        }
        return result(apiCode, msg, null);
    }

    public static <T> ApiResult<T> fail(ApiCode apiCode, T data) {
        if (ApiCode.SUCCESS == apiCode) {
            throw new RuntimeException("失败结果状态码不能为" + ApiCode.SUCCESS.getCode());
        }
        return result(apiCode, data);

    }

    public static <T> ApiResult<Map<String, T>> fail(String key, T value) {
        Map<String, T> map = new HashMap<>(1);
        map.put(key, value);
        return result(ApiCode.FAIL, map);
    }

    public static <T> ApiResult<T> fail() {
        return fail(ApiCode.FAIL);
    }
}